#include <iostream>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>

using namespace std;

void handler(int signo)
{
    cout << "signo :" << signo << endl;
    // sleep(5);

    pid_t id = 0;
    // 循环回收多进程,pengding位图只能保存一个信号，
    //在信号执行的同一时间段可能有多个进程退出
    while (id = waitpid(-1, nullptr, WNOHANG)) //如果一部分退，一部分没有退在handler函数这里就会阻塞在这里出问题
    {
        if (id < 0)
        {
            break;
        }
        cout << "回收进程 id : " << id << endl;
    }
}

int main()
{
    signal(SIGCHLD, SIG_IGN); //Linux支持手动忽略SIGCHLD, 所有的子进程都不要父进程进行等待了！！退出自动回收Z

    for (int i = 0; i < 10; i++)
    {
        pid_t pid = fork();
        if (pid == 0)
        {
            cout << "child is runing !" << endl;
            sleep(1);
            exit(10);
        }
    }

    while (true)
        sleep(1);
    // sleep(10);
    // wait(NULL);

    return 0;
}

// volatile int flag = 0; //使用关键词volatile 以后使用flag变量就必须要访问内存
// // int flag = 0;

// void handler(int signo)
// {
//     cout << "signo :" << signo << endl;
//     flag = 1;
//     cout << "change flag to " << flag << endl;
// }

// int main()
// {
//     signal(2,handler);
//     cout << "pid :" << getpid() << endl;
//     while(!flag);
//     cout << "quit ! " << endl;
//     return 0;
// }

// void handler(int signo)
// {
//     cout<< "get a signo :" << signo <<endl;
//     sleep(1);
// }

// void PrintPending(const sigset_t& pending)
// {
//     for(int signo = 31;signo > 0 ;signo--)
//     {
//         if(sigismember(&pending,signo))
//         {
//             cout<<"1";
//         }
//         else{
//             cout<<"0";
//         }
//     }
//     cout<<endl;
// }

// // void handler(int signo)
// // {
// //     cout<< "get a signo : " << signo <<endl;
// //     sleep(1);
// //     while(true)
// //     {
// //         sigset_t pending;
// //         sigpending(&pending);
// //         PrintPending(pending);
// //         sleep(1);
// //     }
// // }

// //1.sigactoin 在处理一个型号的时候会屏蔽当前处理信号
// //2.sigaction sa_mask 可以添加处理该信号的时候屏蔽的信号
// //3.对于一堆信号同时出现os怎么处理，os是将信号全部处理以后，
// //然后在回到用户态执行用户级代码（处理信号的顺序可以理解为信号也是有对应的优先级的所以处理信号不是顺序的）
// //4.volatile 访问内存
// //5.子进程退出的时候收到17（SIGCHLD）信号
// int main()
// {
//     //2,3,4,5,6
//     signal(2,handler);
//     signal(3,handler);
//     signal(4,handler);
//     signal(5,handler);
//     signal(6,handler);

//     sigset_t mask,omask;

//     sigemptyset(&mask);
//     sigemptyset(&omask);

//     sigaddset(&mask,2);
//     sigaddset(&mask,3);
//     sigaddset(&mask,4);
//     sigaddset(&mask,5);
//     sigaddset(&mask,6);

//     sigprocmask(SIG_SETMASK,&mask,&omask);

//     int cnt = 20;
//     sigset_t pending;
//     cout<< "runing ... pid : " << getpid() <<endl;

//     while(true)
//     {
//         sigpending(&pending);
//         PrintPending(pending);
//         // cout<< "runing ... pid : " << getpid() << "cnt :"  << cnt <<endl;
//         sleep(1);
//         cnt--;
//         if(cnt == 0)
//         {
//             //模拟一下出现多个信号
//             sigprocmask(SIG_SETMASK,&omask,nullptr);
//         }
//     }

//     //sigaction
//     // cout<< "pid : " << getpid() <<endl;
//     // struct sigaction act,oact;
//     // sigset_t mask;
//     // sigaddset(&mask,3);

//     // act.sa_handler = handler;
//     // act.sa_mask = mask;
//     // sigaction(2, &act, &oact);

//     // while(true);
//     return 0;
// }